import { openDB } from 'idb'; // 从 idb 库导入 openDB 函数用于操作 IndexedDB

// 定义数据库名称常量
const DB_NAME = 'ChatDatabase';
// 定义消息对象存储名称常量
const STORE_NAME_MESSAGES = 'messages';
// 定义聊天列表对象存储名称常量
const STORE_NAME_CHAT_LIST = 'chatList';

// ChatDatabase 类负责与 IndexedDB 进行交互
export default class ChatDatabase {
    constructor(userId) {
        this.dbName = DB_NAME; // 设置数据库名称
        this.storeNameMessages = STORE_NAME_MESSAGES; // 设置消息对象存储名称
        this.storeNameChatList = STORE_NAME_CHAT_LIST; // 设置聊天列表对象存储名称
        this.userId = userId; // 设置用户 ID，用于区分不同用户的聊天记录
    }

    // 初始化方法，用于打开或创建数据库
    async init() {
        await this.openDb(); // 调用 openDb 方法来初始化数据库连接
    }

    // 打开数据库并处理升级逻辑的方法
    async openDb() {
        this.db = await openDB(this.dbName, 2, { // 使用 openDB 函数打开指定名称和版本的数据库
            upgrade(db, oldVersion, newVersion) { // 当数据库需要升级时调用此回调函数
                console.log(`Upgrading database from version ${oldVersion} to ${newVersion}`); // 记录升级日志

                // 检查是否已经存在名为 STORE_NAME_MESSAGES 的对象存储，如果不存在则创建它
                if (!db.objectStoreNames.contains(STORE_NAME_MESSAGES)) {
                    const messageStore = db.createObjectStore(STORE_NAME_MESSAGES, { keyPath: 'id', autoIncrement: true }); // 创建消息对象存储，并设置主键为自增的 'id'
                    // 确保在创建对象存储时创建索引
                    messageStore.createIndex('byRoomId', 'roomId', { unique: false }); // 为消息对象存储创建按 roomId 索引
                }

                // 检查是否已经存在名为 STORE_NAME_CHAT_LIST 的对象存储，如果不存在则创建它
                if (!db.objectStoreNames.contains(STORE_NAME_CHAT_LIST)) {
                    const chatListStore = db.createObjectStore(STORE_NAME_CHAT_LIST, { keyPath: 'id' }); // 创建聊天列表对象存储，并设置主键为 'id'
                    chatListStore.createIndex('byChatId', 'id', { unique: false }); // 为聊天列表对象存储创建按 id 索引（这里可能应改为 'userId' 或其他字段）
                }

                console.log('Created object stores and indexes:', STORE_NAME_MESSAGES, STORE_NAME_CHAT_LIST); // 记录创建的对象存储和索引
            }
        });

        console.log('Database opened successfully.'); // 数据库成功打开后记录日志
        console.log('Current object stores:', Array.from(this.db.objectStoreNames)); // 打印当前存在的所有对象存储名称
    }

    // 获取指定聊天的消息列表，支持分页查询
    async getMessages(chatId, limit = 5, lastMessageId = null) {
        try {
            const tx = this.db.transaction([this.storeNameMessages], 'readonly'); // 开始一个只读事务，涉及消息对象存储
            const store = tx.objectStore(this.storeNameMessages); // 获取消息对象存储的引用
            const index = store.index('byChatId'); // 获取按 chatId 索引的引用

            let messages = [];
            if (lastMessageId === null) {
                // 如果没有提供最后一条消息的 ID，则获取最近的消息
                messages = await index.getAll(IDBKeyRange.only(chatId), limit); // 查询特定聊天的所有消息，限制数量
            } else {
                // 如果提供了最后一条消息的 ID，则获取比此 ID 更旧的消息
                messages = await index.getAll(IDBKeyRange.upperBound(lastMessageId, false), limit); // 查询特定聊天中早于指定 ID 的消息，限制数量
            }

            return messages.reverse(); // 返回最新的消息在前
        } catch (error) {
            console.error('Error fetching messages:', error); // 捕获并记录错误
            throw error; // 抛出错误以供调用者处理
        }
    }

    // 获取指定聊天的所有消息
    async getAllMessages(chatId) {
        const tx = this.db.transaction(this.storeNameMessages, 'readonly'); // 开始一个只读事务，涉及消息对象存储
        const store = tx.objectStore(this.storeNameMessages); // 获取消息对象存储的引用
        const index = store.index('byRoomId'); // 获取按 roomId 索引的引用
        return await index.getAll(IDBKeyRange.only(chatId)); // 查询特定聊天的所有消息
    }

    // 保存一组消息到指定聊天中
    async saveMessages(chatId, messages) {
        const tx = this.db.transaction([this.storeNameMessages], 'readwrite'); // 开始一个读写事务，涉及消息对象存储
        const store = tx.objectStore(this.storeNameMessages); // 获取消息对象存储的引用
        messages.forEach(message => {
            store.put(message); // 将每条消息保存到对象存储中
        });
        await tx.done; // 等待事务完成
    }

    // 保存聊天列表到数据库
    async saveChatList(chatList) {
        const tx = this.db.transaction([this.storeNameChatList], 'readwrite'); // 开始一个读写事务，涉及聊天列表对象存储
        const store = tx.objectStore(this.storeNameChatList); // 获取聊天列表对象存储的引用
        chatList.forEach(chat => {
            store.put(chat); // 将每个聊天项保存到对象存储中
        });
        await tx.done; // 等待事务完成
    }

    // 加载聊天列表
    async loadChatList() {
        try {
            const tx = this.db.transaction([this.storeNameChatList], 'readonly'); // 开始一个只读事务，涉及聊天列表对象存储
            const store = tx.objectStore(this.storeNameChatList); // 获取聊天列表对象存储的引用
            // 直接获取对象存储中的所有记录，不使用索引
            const result = await store.getAll(); // 查询聊天列表中的所有记录
            return result; // 返回查询结果
        } catch (error) {
            console.error('Error loading chat list:', error); // 捕获并记录错误
            throw error; // 抛出错误以供调用者处理
        }
    }
}